﻿using SharpSoft.WPF.Controls.Primitives;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SharpSoft.WPF.Controls
{
    /// <summary>
    /// 范围选择器，可以选取范围内一大一小两个值。
    /// </summary>
    [TemplatePart(Name = "PART_TRACK", Type = typeof(Track2))]
    [TemplatePart(Name = "PART_TrackBackground", Type = typeof(FrameworkElement))]
    public class RangeSlider : RangeBase
    {
        static RangeSlider()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(typeof(RangeSlider)));

            EventManager.RegisterClassHandler(typeof(RangeSlider), Thumb.DragDeltaEvent, new DragDeltaEventHandler(RangeSlider.OnThumbDragDelta));
        }


        #region inner

        protected virtual void UpdateLowerValue(double value)
        {
            if (this.LowerValue != value)
            {
                this.SetCurrentValue(LowerValueProperty, Math.Max(this.Minimum, Math.Min(this.HigherValue, value)));
            }

        }
        protected virtual void UpdateHigherValue(double value)
        {
            if (this.HigherValue != value)
            {
                this.SetCurrentValue(HigherValueProperty, Math.Min(this.Maximum, Math.Max(this.LowerValue, value)));
            }

        }


        private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
        {
            if (sender is RangeSlider rangeSlider)
            {
                rangeSlider.OnThumbDragDelta(e);
            }
        }
        protected virtual void OnThumbDragDelta(DragDeltaEventArgs e)
        {
            if (this._track == null)
            {
                return;
            }
            if (e.OriginalSource is Thumb thumb)
            {
                var distance = this.Orientation == Orientation.Horizontal ? e.HorizontalChange : e.VerticalChange;
                if (thumb == this._track.LowerThumb)
                {
                    var offset = this._track.ValueFromDistance(distance);

                    this.UpdateLowerValue(this.LowerValue + offset);
                }
                else if (thumb == this._track.HigherThumb)
                {
                    var offset = this._track.ValueFromDistance(distance);

                    this.UpdateHigherValue(this.HigherValue + offset);
                }
            }
        }

        private void ResetTrackBackground()
        {
            if (_trackBg != null)
            {
                var thumbLength = this.ThumbLength;
                if (this.Orientation == Orientation.Horizontal)
                {
                    this._trackBg.HorizontalAlignment = HorizontalAlignment.Stretch;
                    this._trackBg.VerticalAlignment = VerticalAlignment.Center;
                    this._trackBg.Height = TrackBackgroundSpacing;
                    this._trackBg.Width = float.NaN;
                    this._trackBg.Margin = new Thickness(thumbLength, 0, thumbLength, 0);
                }
                else
                {
                    this._trackBg.HorizontalAlignment = HorizontalAlignment.Center;
                    this._trackBg.VerticalAlignment = VerticalAlignment.Stretch;
                    this._trackBg.Width = TrackBackgroundSpacing;
                    this._trackBg.Height = float.NaN;
                    this._trackBg.Margin = new Thickness(0, thumbLength, 0, thumbLength);
                }
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this._track = this.GetTemplateChild("PART_TRACK") as Track2;
            this._trackBg = this.GetTemplateChild("PART_TrackBackground") as FrameworkElement;

        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);

            if (e.Property == LowerValueProperty)
            {
                this.OnLowerValueChanged();
            }
            else if (e.Property == HigherValueProperty)
            {
                this.OnHigherValueChanged();
            }
            else if (e.Property == OrientationProperty || e.Property == ThumbLengthProperty
               || e.Property == ActualHeightProperty || e.Property == ActualWidthProperty)
            {
                ResetTrackBackground();
            }
        }

        protected override Size MeasureOverride(Size constraint)
        {
            ///未明确指定高度/宽度时，使用默认的宽度/高度
            if (Orientation== Orientation.Horizontal)
            {
                if (double.IsNaN(this.Height))
                {
                    constraint.Height = SystemParameters.HorizontalScrollBarHeight;
                }
            }
            else
            {
                if (double.IsNaN(this.Width))
                {
                    constraint.Width = SystemParameters.VerticalScrollBarWidth;
                }
            }
            return base.MeasureOverride(constraint);
        }

        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            return base.ArrangeOverride(arrangeBounds);
        }
        #endregion

        #region 成员
        const double TrackBackgroundSpacing = 4d;

        private Track2 _track;
        private FrameworkElement _trackBg;


        #endregion

        #region 属性

        /// <summary>
        /// 高值
        /// </summary>
        public double HigherValue
        {
            get { return (double)GetValue(HigherValueProperty); }
            set
            {
                UpdateHigherValue(value);
            }
        }

        public static readonly DependencyProperty HigherValueProperty =
            DependencyProperty.Register("HigherValue", typeof(double), typeof(RangeSlider), new PropertyMetadata(0d));


        public event RoutedEventHandler HigherValueChanged
        {
            add { AddHandler(HigherValueChangedEvent, value); }
            remove { RemoveHandler(HigherValueChangedEvent, value); }
        }

        public static readonly RoutedEvent HigherValueChangedEvent = EventManager.RegisterRoutedEvent(
        "HigherValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RangeSlider));

        protected virtual void OnHigherValueChanged()
        {
            RoutedEventArgs args = new RoutedEventArgs();
            args.RoutedEvent = RangeSlider.HigherValueChangedEvent;
            this.RaiseEvent(args);
        }


        /// <summary>
        /// 低值
        /// </summary>
        public double LowerValue
        {
            get { return (double)GetValue(LowerValueProperty); }
            set
            {
                UpdateLowerValue(value);
            }
        }

        public static readonly DependencyProperty LowerValueProperty =
            DependencyProperty.Register("LowerValue", typeof(double), typeof(RangeSlider), new PropertyMetadata(0d));


        public event RoutedEventHandler LowerValueChanged
        {
            add { AddHandler(LowerValueChangedEvent, value); }
            remove { RemoveHandler(LowerValueChangedEvent, value); }
        }

        public static readonly RoutedEvent LowerValueChangedEvent = EventManager.RegisterRoutedEvent(
        "LowerValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RangeSlider));

        protected virtual void OnLowerValueChanged()
        {
            RoutedEventArgs args = new RoutedEventArgs();
            args.RoutedEvent = RangeSlider.LowerValueChangedEvent;
            this.RaiseEvent(args);
        }


        /// <summary>
        /// 方向
        /// </summary>
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangeSlider), new PropertyMetadata(Orientation.Horizontal));


        /// <summary>
        /// 滑块的宽度（水平）/高度（垂直）
        /// </summary>
        public double ThumbLength
        {
            get { return (double)GetValue(ThumbLengthProperty); }
            set { SetValue(ThumbLengthProperty, value); }
        }

        public static readonly DependencyProperty ThumbLengthProperty =
            DependencyProperty.Register("ThumbLength", typeof(double), typeof(RangeSlider), new PropertyMetadata(10d));


        #endregion
    }
}
